/*
 * 在ASP.NET Core中有多种缓存数据的方式，Orchard Core也使用这些方式。例如，内容项使用IMemoryCache服务进行缓存。
 * 内存缓存将数据副本保存在本地服务器的内存中，这在大多数情况下可能就足够了。但是，某些功能需要一些额外的功能
 * 和更复杂的缓存方式，比如形状（shapes）。在Orchard Core中有一个所谓的动态缓存（Dynamic Cache），它建立在
 * 分布式缓存（Distributed Cache）之上。分布式缓存在集中位置维护缓存，集群中的服务器可以访问该位置。
 * 在Orchard Core中，这也是内存缓存，但为使用Redis等提供了可能性。在本教程中，我们将看到缓存DateTime对象的
 * 几个示例，还将演示形状缓存。
 * 
 * 主要功能：
 * - 演示ASP.NET Core内存缓存的使用
 * - 展示Orchard Core动态缓存的使用
 * - 演示基于路由的缓存机制
 * - 展示缓存失效和更新机制
 * - 演示形状缓存的使用
 */

using Lombiq.TrainingDemo.Services;
using Lombiq.TrainingDemo.ViewModels;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace Lombiq.TrainingDemo.Controllers;

/// <summary>
/// 缓存控制器 - 演示Orchard Core中的各种缓存机制
/// 
/// 主要用途：
/// - 演示ASP.NET Core内存缓存的使用
/// - 展示Orchard Core动态缓存的使用
/// - 演示基于路由的缓存机制
/// - 展示缓存失效和更新机制
/// - 演示形状缓存的使用
/// 
/// 使用场景：
/// - 缓存DateTime对象的不同方式
/// - 基于路由的缓存变化
/// - 缓存失效和更新
/// - 形状缓存的实际应用
/// 
/// 设计原因：
/// - 展示Orchard Core缓存系统的最佳实践
/// - 演示不同缓存策略的使用场景
/// - 提供缓存性能优化的示例
/// - 展示分布式缓存的优势
/// 
/// 设计模式：
/// - 依赖注入模式：通过构造函数注入缓存服务
/// - 服务模式：使用专门的缓存服务处理缓存逻辑
/// - 视图模型模式：使用ViewModel传递缓存数据
/// - 路由模式：基于不同路由实现缓存变化
/// </summary>
public sealed class CacheController : Controller
{
    // 实际的缓存实现在一个服务中，我们很快就会研究它。
    private readonly IDateTimeCachingService _dateTimeCachingService;

    /// <summary>
    /// 构造函数 - 注入缓存服务
    /// </summary>
    /// <param name="dateTimeCachingService">日期时间缓存服务，用于处理各种缓存操作</param>
    public CacheController(IDateTimeCachingService dateTimeCachingService) => _dateTimeCachingService = dateTimeCachingService;

    /// <summary>
    /// 缓存演示主页面
    /// 
    /// 功能说明：
    /// - 演示三种不同的DateTime缓存方式
    /// - 展示内存缓存的使用
    /// - 展示动态缓存的使用
    /// - 展示基于路由的缓存变化
    /// 
    /// 缓存方式：
    /// - 内存缓存：使用ASP.NET Core内置的IMemoryCache
    /// - 动态缓存：使用Orchard Core提供的DynamicCache，30秒过期
    /// - 路由缓存：仅针对特定路由进行缓存
    /// 
    /// 访问方式：
    /// - URL：/Lombiq.TrainingDemo/Cache/Index
    /// </summary>
    /// <returns>返回包含缓存数据的视图</returns>
    // 在这个操作中，我们将以三种不同的方式缓存DateTime。您可以在/Lombiq.TrainingDemo/Cache/Index下打开它
    public async Task<ActionResult> Index()
    {
        // 这个将使用内置的ASP.NET Core IMemoryCache进行缓存。
        var memoryCachedDateTime = await _dateTimeCachingService.GetMemoryCachedDateTimeAsync();

        // 这个将使用Orchard Core提供的DynamicCache。它将有30秒的过期时间。
        var dynamicCachedDateTimeWith30SecondsExpiry =
            await _dateTimeCachingService.GetDynamicCachedDateTimeWith30SecondsExpiryAsync();

        // 最后这个日期将仅针对此路由进行缓存。
        var dynamicCachedDateTimeVariedByRoutes =
            await _dateTimeCachingService.GetDynamicCachedDateTimeVariedByRoutesAsync();

        // 下一站：Services/DateTimeCachingService.cs

        return View("Index", new CacheViewModel
        {
            MemoryCachedDateTime = memoryCachedDateTime,
            DynamicCachedDateTimeWith30SecondsExpiry = dynamicCachedDateTimeWith30SecondsExpiry,
            DynamicCachedDateTimeVariedByRoutes = dynamicCachedDateTimeVariedByRoutes,
        });
    }

    /// <summary>
    /// 不同路由的缓存测试
    /// 
    /// 功能说明：
    /// - 返回与Index相同的页面
    /// - 但路由不同，可以测试基于路由的缓存
    /// - 演示路由变化对缓存的影响
    /// 
    /// 访问方式：
    /// - URL：/Lombiq.TrainingDemo/Cache/DifferentRoute
    /// </summary>
    /// <returns>返回与Index相同的视图</returns>
    // 这个操作将产生与Index相同的页面，但是路由将不同，所以可以测试基于路由的缓存。
    // 您可以在/Lombiq.TrainingDemo/Cache/DifferentRoute下打开它
    public Task<ActionResult> DifferentRoute() =>
        Index();

    /// <summary>
    /// 失效DateTime缓存
    /// 
    /// 功能说明：
    /// - 失效内存缓存和所有基于路由的缓存
    /// - 调用此操作将重定向回Index页面
    /// - 您会注意到日期值已更新
    /// 
    /// 缓存失效：
    /// - 清除内存缓存
    /// - 清除所有基于路由的缓存
    /// - 强制重新生成缓存数据
    /// 
    /// 访问方式：
    /// - URL：/Lombiq.TrainingDemo/Cache/InvalidateDateTimeCache
    /// </summary>
    /// <returns>重定向到Index页面</returns>
    // 这个操作将失效内存缓存和所有基于路由的缓存。调用此操作将重定向回Index页面，
    // 您会注意到日期值已更新。您可以在/Lombiq.TrainingDemo/Cache/InvalidateDateTimeCache下打开它
    public async Task<ActionResult> InvalidateDateTimeCache()
    {
        await _dateTimeCachingService.InvalidateCachedDateTimeAsync();

        return RedirectToAction("Index");
    }

    /// <summary>
    /// 形状缓存演示
    /// 
    /// 功能说明：
    /// - 展示Orchard Core如何最充分地利用动态缓存
    /// - 演示形状（shapes）的缓存机制
    /// - 展示形状缓存的性能优势
    /// 
    /// 访问方式：
    /// - URL：/Lombiq.TrainingDemo/Cache/Shape
    /// </summary>
    /// <returns>返回形状缓存演示视图</returns>
    // 现在让我们看看Orchard Core如何最充分地利用动态缓存。在这个操作中，您将看到形状是如何被缓存的。
    // 您可以在/Lombiq.TrainingDemo/Cache/Shape下打开它
    public ActionResult Shape() =>
        View();

    // 下一站：Views/Cache/Shape.cshtml
}
